package generator;

import java.util.Stack;

import javax.swing.JFrame;

import data.cell;

public class mazegen 
{
	private final int x = 64;
	private final int y = 64;
	private int rX;
	private int rY;
	private int totalCells;
	private int visitedCells;
	private int cellWalledCounter;
	
	private cell[][] maze;
	private cell currentCell;
	private cell foundCell = null;
	
	private Stack<cell> cellStack;
	private JFrame frame;
	
	public mazegen(JFrame frame)
	{
		this.maze = new cell[x][y];
		for (int i = 0; i < x; i++)
		{
			for (int j = 0; j < y; j++)
			{
				this.maze[i][j] = new cell(i,j);
			}
		}
		maze[0][63].setStart(true);
		maze[63][0].setExit(true);
		
		this.frame = frame;
	}
	
	public void generate()
	{
		//create a CellStack (LIFO) to hold a list of cell locations 
		cellStack = new Stack<cell>();
		
		//set TotalCells = number of cells in grid 
		totalCells = x * y;
		
		//choose a cell at random and call it CurrentCell 
		rX  = (int)Math.round(Math.random()*63);
		rY  = (int)Math.round(Math.random()*63);
		currentCell = maze[rX][rY];
		
		//set VisitedCells = 1 
		visitedCells = 1;
		
		//while VisitedCells < TotalCells 
		while(visitedCells < totalCells)
		{
			//System.out.println("VisitedCells : "+visitedCells);
		    //find all neighbors of CurrentCell with all walls intact
			cell[] walledArray = new cell[4];
			cellWalledCounter = 0;
			for(int i =0;i<4;i++)
			{
				foundCell = null;
				switch(i)
				{
					case 0: // North
					{
						if((currentCell.getY() - 1) < 0)
							break;
						else
							foundCell = maze[currentCell.getX()][currentCell.getY()-1];
					}
					break;
					case 1: // East
					{
						if((currentCell.getX()+ 1) > 63)
							break;
						else
							foundCell = maze[currentCell.getX()+1][currentCell.getY()];
					}
					break;
					case 2: // South
					{
						if((currentCell.getY() + 1) > 63)
							break;
						else
							foundCell = maze[currentCell.getX()][currentCell.getY()+1];
					}
					break;
					case 3: // West
					{
						if((currentCell.getX() - 1) < 0)
							break;
						else
							foundCell = maze[currentCell.getX()-1][currentCell.getY()];
					}
					break;
				}
				if(foundCell != null)
				{
					if(foundCell.isFullyWalled())
					{
						walledArray[cellWalledCounter] = foundCell;
						cellWalledCounter++;
					}
				}
					
			}
			
		    //if one or more found 
			if(cellWalledCounter > 0)
			{
		        //choose one at random
				int randInt = (int)Math.round(Math.random()*(cellWalledCounter - 1));
				//System.out.println("cellWalledCounter is "+cellWalledCounter);
				//System.out.println("chosen randomInt is "+randInt);
				int targetX = walledArray[randInt].getX();
				int targetY = walledArray[randInt].getY();
				
				//knock down the wall between it and CurrentCell 
				
				//East
				if(targetX - 1 == currentCell.getX())
				{
					currentCell.setWallEast(false);
					maze[targetX][targetY].setWallWest(false);
				}
				//West
				else if(targetX + 1 == currentCell.getX())
				{
					currentCell.setWallWest(false);
					maze[targetX][targetY].setWallEast(false);
				}
				//South -- a multidimensional array start in the upper left corner
				else if(targetY - 1 == currentCell.getY())
				{
					currentCell.setWallSouth(false);
					maze[targetX][targetY].setWallNorth(false);
				}
				//North -- a multidimensional array start in the upper left corner
				else if (targetY + 1 == currentCell.getY())
				{
					currentCell.setWallNorth(false);
					maze[targetX][targetY].setWallSouth(false);
				}
		        
		        //push CurrentCell location on the CellStack 
				cellStack.push(currentCell);
				
		        //make the new cell CurrentCell 
				currentCell = walledArray[randInt];
				
		        //add 1 to VisitedCells 
				visitedCells++;
				frame.repaint();
				
				/*try {
					Thread.sleep(25);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}*/
			}
			else 
			{
		        //pop the most recent cell entry off the CellStack 
		        //make it CurrentCell endIf
				currentCell = cellStack.pop();
			}
		}
	}
	
	public int getX()
	{
		return this.x;
	}
	
	public int getY()
	{
		return this.y;
	}
	
	public cell[][] getMaze()
	{
		return this.maze;
	}
}
